<?php

	/**
	 * <version greek="beta" major="1" minor="0">Cochin Splash Hen</version>
	 * <author email="njones@art-k-tec.com">Nika Jones</author>
	 * <copyright start="2007">Art-k-tec Systems, LLC</copyright>
	 * <license type="Apache2.0" href="http://www.opensource.org/licenses/apache2.0.php">Apache License, Version 2.0</license>
	 */

	class bHttp {
		private static $nMajor =1;
		private static $nMinor =0;
		private static $sRevision ="0000";
		
		const NULL ="\0";
		const GET_URL =0;
		const POST_URL =1;
		const POST_XML =2;
		
		private $aProperty;
		private $aHeader;
		
		private $sRootNode;
		private $sUrl;
		
		///<summary>
		///   The constructor
		///</summary>
		public function __construct($sRootNode =__CLASS__) {
			
			$this->sRootNode =$sRootNode;
			$this->aProperty =array();
		}
		
		public static function version() { return self::$nMajor.'.'.self::$nMinor.'.'.self::$sRevision; }
		
		///<summary>
		///   Sets one of the headers that will be passed
		///</summary>
		///<param type="string" name="sKey">The key part of the header</param>
		///<param type="string" name="sValue" optional="true">The value part of the header</param>
		public function SetHeader($sKey, $sValue ='') {
			
			if($sValue ==null) {
				
				unset($this->aHeader[$sKey]);
			} else {
				
				$this->aHeader[$sKey] =$sValue;
			}
		}
		
		///<summary>
		///   Send a GET url in the form of a REST request (i.e. url/{value1}/{value...})
		///</summary>
		///<param type="string" name="sUrl">The url to send the REST request</param>
		public function RestGet($sUrl) {
			$sResponse =file_get_contents($sUrl.$this->AsPath());
			
			return $sResponse;
		}
		
		///<summary>
		///   Send a POST url in the form of a rest request
		///</summary>
		///<param type="string" name="sUrl">The url of the location</param>
		///<param type="string|array" name="mPayload" optional="true">
		///   The post attribiutes to send
		///</param>
		public function RestPost($sUrl, $mPayload =array()) {
			
			if(is_string($mPayload)) { $mPayload =array('payload' =>$mPayload); }
			
			$sResponse =$this->Post($sUrl.$this->AsPath(), $mPayload);
			
			return $sResponse;
		}
		
		///<summary>
		///   Send a REST PUT url in the form of a rest request
		///</summary>
		///<param type="string" name="sUrl">The base url of the rest request</param>
		///<param type="array|string" name="mPayload" optional="true">
		///   The parameters to be PUT to the server in a array("key"=>"value")
		///   or as a string "value".
		///</param>
		public function RestPut($sUrl, $mPayload =array()) {
			
			if(is_string($mPayload)) { $mPayload =array('payload' =>$mPayload); }
			
			$sResponse =$this->Put($sUrl.$this->AsPath(), $mPayload);

			return $sResponse;
		}
		
		///<summary>
		///   Send a url with a DELETE header REST style.
		///</summary>
		///<param type="string" name="sUrl">The base url to send</param>
		///<returns type="binary|string">The response from the server</returns>
		public function RestDelete($sUrl) {
			$sResponse =$this->Delete($sUrl.$this->AsPath());

			return $sResponse;
		}
		
		///<summary>
		///   Send a url with GET querystring parameters
		///</summary>
		///<param type="string" name="sUrl">The url to GET from</param>
		///<returns type="binary|string">The response from the server</returns>
		public function UrlGet($sUrl) {
			$sResponse =file_get_contents($sUrl.$this->AsQueryString());
			
			return $sResponse;
		}
		
		///<summary>
		///   Post the object properties (and optional payload) to a server
		///</summary>
		///<param type="string" name="sUrl">The url to post to</param>
		///<param type="array|string" name="mPayload" optional="true">
		///   additional parameters to post to the server
		///</param>
		///<returns type="binary|string">The response from the server</returns>
		public function UrlPost($sUrl, $mPayload =array()) {
			
			if(is_string($mPayload)) { $mPayload =array('payload' =>$mPayload); }
			
			$sReponse =$this->Post($sUrl, $mPayload);
			
			return $sResponse;
		}
		
		///<summary>
		///   Sets or Gets the rootnode value of this object for XML output
		///<summary>
		///<param type="string" name="sRootNode">A valid QName Xml node name</param>
		///<returns type="string" optional="true">The set root nodename</returns>
		public function RootNode($sRootNode =null) {
			
			if($sRootNode ==null) {
				
				return $this->sRootNode;
			} else {
				
				$this->sRootNode =$sRootNode;
			}
		}
		
		///<summary>
		///   Returns the properties of this object as XML
		///</summary>
		///<returns type="string">The XML</returns>
		public function AsXml() {
			static $nStack =1;
			$sReturn =$nStack ==1 && !empty($this->aProperty) ? "<{$this->sRootNode}>" : '';
			
			foreach($this->aProperty as $mProperty=>$mValue) {
				
				if($mValue instanceof bHttp) { $nStack++; $mValue =$mValue->AsXml(); $nStack--; }
				$sReturn .="<{$mProperty}>{$mValue}</{$mProperty}>";
			}
			
			$sReturn .=$nStack ==1 && !empty($this->aProperty) ? "</{$this->sRootNode}>" : '';
			
			return trim($sReturn);
		}
		
		///<summary>
		///   Returns the properties of this object as a url path (ie. {value}/{value}/...)
		///</summary>
		///<returns type="string">The url path</returns>
		public function AsPath() {
			static $nStack =1;
			$sReturn =$nStack && !empty($this->aProperty) ==1 ? '/' : '';
			$bInLoop =false;
			
			foreach($this->aProperty as $mValue) {
				$bInLoop =true;
				
				if($mValue instanceof bHttp) { $nStack++; $mValue =$mValue->AsPath(); $nStack--; }
				$sReturn .=urlencode($mValue).'/';
			}
			
			$sReturn =$nStack ==1 && $bInLoop ? substr($sReturn, 0, strlen($sReturn) -1) : $sReturn;
			
			return trim($sReturn);
		}
		
		///<summary>
		///   Returns the properties of this object as a url querystring 
		///   (i.e. key=value&key=value) 
		///</summary>
		///<returns type="string">The query string</returns>
		public function AsQueryString($aArray =self::NULL) {
			static $nStack =1;
			
			$bLoop =false;
			$aLoop =($aArray ==self::NULL ? $this->aProperty : (empty($aArray) ? array() : $aArray));
			
			$sReturn =($nStack ==1 && !empty($aLoop) ? '?' : '');
			
			foreach($aLoop as $mProperty=>$mValue) {
				$bLoop =true;
				
				if($mValue instanceof bHttp) { $nStack++; $mValue =$mValue->AsQueryString(); $nStack--; }
				$sReturn .=urlencode($mProperty).'='.urlencode($mValue).'&';
			}
			
			$sReturn =$nStack ==1 && $bLoop ? substr($sReturn, 0, strlen($sReturn) -1) : $sReturn;
			
			return trim($sReturn);
		}
		
		public function __get($sKey) {
			
			if(isset($this->aProperty[$sKey])) {
				
				$mReturn =new bHttp(null);
			} else {
				
				$mReturn =$this->aProperty[$sKey];
			}
			return $mReturn;
		}
		
		public function __set($sKey, $sValue) {
			
			$this->aProperty[$sKey] =$sValue;
		}
		
		private function Post($sUrl, $mData) {
			$aHead = array('http' => array('method' => 'POST'));
			
			return $this->Send($sUrl, $mData, $aHead);
		}
		
		private function Put($sUrl, $mData) {
			$aHead = array('http' => array('method' => 'PUT'));
			
			return $this->Send($sUrl, $mData, $aHead);
		}
		
		private function Delete($sUrl) {
			$aHead = array('http' => array('method' => 'DELETE'));
			
			return $this->Send($sUrl, null, $aHead);
		}
		
		private function Send($sUrl, $mData, $aHead) {

			if($mData !==array()) {
				$aHead['http']['content'] =substr($this->AsQueryString(), 1)
					.(($s =$this->AsQueryString($mData)) =='' ? '' : '&'.substr($s, 1));
			}
			
			if ($this->aHeader !== null) {
				
				$aHead['http']['header'] = $this->aHeader;
			}
			
			$oContext =stream_context_create($aHead);
			
			$sResponse =@file_get_contents($sUrl, FILE_BINARY, $oContext);
			
			return $sResponse;
		}
	}

?>